package com.lan.utils;


import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.FastDateFormat;

import java.text.ParseException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;

public class DateUtils {


    public static FastDateFormat sdf_YYYY_MM_DD_HHMMSS = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYY_M_D_HMS = FastDateFormat.getInstance("yyyy-M-d H:m:s", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYY_M_D_HM = FastDateFormat.getInstance("yyyy-M-d H:m", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYYMMDDHHmmss = FastDateFormat.getInstance("yyyyMMddHHmmss", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYYMMDDHHmm = FastDateFormat.getInstance("yyyyMMddHHmm", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYYMMDDHms = FastDateFormat.getInstance("yyyyMMddHms", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYYMDHms = FastDateFormat.getInstance("yyyyMdHms", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYY_MM_DD = FastDateFormat.getInstance("yyyy-MM-dd", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYY_M_D = FastDateFormat.getInstance("yyyy-M-d", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYYMMDD = FastDateFormat.getInstance("yyyyMMdd", TimeZone.getDefault());

//    public static SimpleDateFormat sdf_YYYYMD = new SimpleDateFormat("yyyyMd");

    public static FastDateFormat sdf_YYYY__MM__DD__HH = FastDateFormat.getInstance("yyyy/MM/dd/HH", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYY__MM__DD = FastDateFormat.getInstance("yyyy/MM/dd", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYY__M__D = FastDateFormat.getInstance("yyyy/M/d", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYY__MM__DD_HHMMSS = FastDateFormat.getInstance("yyyy/MM/dd HH:mm:ss", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYY__M__D_HMS = FastDateFormat.getInstance("yyyy/M/d H:m:s", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYY__M__D_HM = FastDateFormat.getInstance("yyyy/M/d H:m", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYYMMDD_HHMMSS = FastDateFormat.getInstance("yyyyMMdd HH:mm:ss", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYYMD_HMS = FastDateFormat.getInstance("yyyyMd H:m:s", TimeZone.getDefault());

    public static FastDateFormat sdf_YYYYMD_HM = FastDateFormat.getInstance("yyyyMd H:m", TimeZone.getDefault());

    public static FastDateFormat sdf_HHMMSS = FastDateFormat.getInstance("HHmmss", TimeZone.getDefault());


    public static Date str2Date_YYYY_MM_DD(String str) throws ParseException {
        return sdf_YYYY_MM_DD.parse(str);
    }

    public static Date str2Date_YYYY_MM_DD_HHMMSS(String str) throws ParseException {
        return sdf_YYYY_MM_DD_HHMMSS.parse(str);
    }

    public static Date str2Date_YYYYMMDDHHmmss(String str) throws ParseException {
        return sdf_YYYYMMDDHHmmss.parse(str);
    }

    public static Date str2Date_YYYYMMDDHHmm(String str) throws ParseException {
        return sdf_YYYYMMDDHHmm.parse(str);
    }

    public static Date str2Date_YYYYMMDDHms(String str) throws ParseException {
        return sdf_YYYYMMDDHms.parse(str);
    }


    public static Date str2Date_YYYYMMDD(String str) throws ParseException {
        return sdf_YYYYMMDD.parse(str);
    }

    public static Date str2Date_YYYY_M_D(String str) throws ParseException {
        return sdf_YYYY_M_D.parse(str);
    }


    public static Date str2Date_YYYY_M_D_HMS(String str) throws ParseException {
        return sdf_YYYY_M_D_HMS.parse(str);
    }

    public static Date str2Date_YYYY_M_D_HM(String str) throws ParseException {
        return sdf_YYYY_M_D_HM.parse(str);
    }

    public static Date str2Date_YYYY__M__D_HMS(String str) throws ParseException {
        return sdf_YYYY__M__D_HMS.parse(str);
    }


    public static Date str2Date_YYYY__M__D_HM(String str) throws ParseException {
        return sdf_YYYY__M__D_HM.parse(str);
    }


    public static Date str2Date_YYYYMDHms(String str) throws ParseException {
        return sdf_YYYYMDHms.parse(str);
    }

    public static Date str2Date_YYYYMD_HMS(String str) throws ParseException {
        return sdf_YYYYMD_HMS.parse(str);
    }

    public static Date str2Date_YYYY_HM(String str) throws ParseException {
        return sdf_YYYYMD_HM.parse(str);
    }

    public static Date str2Date_YYYY__MM__DD_HHMMSS(String str) throws ParseException {
        return sdf_YYYY__MM__DD_HHMMSS.parse(str);
    }

    public static Date str2Date_YYYY__MM__DD(String str) throws ParseException {
        return sdf_YYYY__MM__DD.parse(str);
    }

    public static Date str2Date_YYYY__M__D(String str) throws ParseException {
        return sdf_YYYY__M__D.parse(str);
    }

    public static Date str2Date_YYYYMMDD_HHMMSS(String str) throws ParseException {
        return sdf_YYYYMMDD_HHMMSS.parse(str);
    }


    public static String date2Str_YYYYMMDD(Date date) {
        return sdf_YYYYMMDD.format(date);
    }

    public static String date2Str_YYYY__MM__DD__HH(Date date) {
        return sdf_YYYY__MM__DD__HH.format(date);
    }

    public static String date2Str_YYYY__MM__DD(Date date) {
        return sdf_YYYY__MM__DD.format(date);
    }

    public static String date2Str_YYYY__MM__DD_HHMMSS(Date date) {
        return sdf_YYYY__MM__DD_HHMMSS.format(date);
    }


    public static String date2Str_YYYYMMDDHHmmss(Date date) {
        return sdf_YYYYMMDDHHmmss.format(date);
    }

    public static String date2Str_YYYY_MM_DD_HHMMSS(Date date) {
        return sdf_YYYY_MM_DD_HHMMSS.format(date);
    }

    public static String date2Str_YYYY_MM_DD(Date date) {
        return sdf_YYYY_MM_DD.format(date);
    }


    public static String date2Str_HHMMSS(Date date) {
        return sdf_HHMMSS.format(date);
    }


    public static LocalDateTime dateToLocalDateTime(final Date date) {
        if (null == date) {
            return null;
        }
        final Instant instant = date.toInstant();
        final ZoneId zoneId = ZoneId.systemDefault();
        final LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
        return localDateTime;
    }


    public static Date localDateTimeToDate(final LocalDateTime localDateTime) {
        if (null == localDateTime) {
            return null;
        }
        final ZoneId zoneId = ZoneId.systemDefault();
        final ZonedDateTime zdt = localDateTime.atZone(zoneId);
        final Date date = Date.from(zdt.toInstant());
        return date;
    }


    public static int daysBetween(String startStr, String endStr) throws ParseException {
        Date start = str2Date_YYYY_MM_DD(startStr);
        Date end = str2Date_YYYY_MM_DD(endStr);
        long l = end.getTime() - start.getTime();
        if (l == 0) {
            return 0;
        }
        return (int) (l / (1000 * 3600 * 24));
    }


    public static int daysBetween(Date start, Date end) {
        start = getDayStart(start);
        end = getDayStart(end);
        long l = end.getTime() - start.getTime();
        if (l == 0) {
            return 0;
        }
        return (int) (l / (1000 * 3600 * 24));
    }

    public static Date getDayStart(Date date) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        LocalDateTime t = LocalDateTime.of(localDateTime.getYear(), localDateTime.getMonth(), localDateTime.getDayOfMonth(), 0, 0, 0);
        return localDateTimeToDate(t);
    }

    /**
     * 结束时间
     *
     * @param date
     * @throws
     * @Title: getDayEnd
     */
    public static Date getDayEnd(Date date) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        LocalDateTime t = LocalDateTime.of(localDateTime.getYear(), localDateTime.getMonth(), localDateTime.getDayOfMonth(), 23, 59, 59);
        return localDateTimeToDate(t);
    }


    public static Date getMonthStart(Date date) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        LocalDateTime t = LocalDateTime.of(localDateTime.getYear(), localDateTime.getMonth(), 1, 0, 0, 0);
        return localDateTimeToDate(t);
    }


    public static Date getMonthNextStart(Date date) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        LocalDateTime t = LocalDateTime.of(localDateTime.getYear(), localDateTime.getMonth(), 1, 0, 0, 0);
        t = t.plusMonths(1).withDayOfMonth(1);
        return localDateTimeToDate(t);
    }


    public static Date getMonthEnd(Date date) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        LocalDateTime t = LocalDateTime.of(localDateTime.getYear(), localDateTime.getMonth(), 1, 0, 0, 0);
        t = t.plusMonths(1).plusSeconds(-1);
        return localDateTimeToDate(t);
    }

    /**
     * 当月最后一天
     *
     * @param date
     * @throws
     * @Title: getLastDayOfMonth
     */
    public static Date getLastDayOfMonth(Date date) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        LocalDateTime t = LocalDateTime.of(localDateTime.getYear(), localDateTime.getMonth(), localDateTime.getDayOfMonth(), 23, 59, 59);
        return localDateTimeToDate(t);
    }


    /**
     * 当月最后一天
     *
     * @param date
     * @throws
     * @Title: getFirstDayOfMonth
     */
    public static Date getFirstDayOfMonth(Date date) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        LocalDateTime t = LocalDateTime.of(localDateTime.getYear(), localDateTime.getMonth(), localDateTime.getDayOfMonth(), 0, 0, 0);
        return localDateTimeToDate(t);
    }


    /**
     * 当前天 像前推多少天
     */
    public static Date addDay(Date date, int num) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        localDateTime = localDateTime.plusDays(num);
        return localDateTimeToDate(localDateTime);
    }

    public static int getDay(Date date) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        return localDateTime.getDayOfMonth();
    }

    public static Date beforeDays(Date date, int n) {
        LocalDateTime localDateTime = dateToLocalDateTime(date);
        localDateTime = localDateTime.plusDays(-n);
        return localDateTimeToDate(localDateTime);
    }


    public static Date rand(Date date, boolean bool) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        if (bool) {
            calendar.set(Calendar.HOUR, RandomUtils.random(new int[]{7, 8}));
        } else {
            calendar.set(Calendar.HOUR, RandomUtils.random(new int[]{17, 18, 19, 20, 21, 22}));
        }
        calendar.set(Calendar.MINUTE, RandomUtils.random(60));
        calendar.set(Calendar.SECOND, RandomUtils.random(60));
        return calendar.getTime();
    }


    public static Date str2Date1(String txt, boolean bool) throws ParseException {
        boolean is_ = txt.indexOf('-') > 0 ? true : false;
        boolean is__ = txt.indexOf("/") > 0 ? true : false;
        boolean is___ = txt.indexOf(":") > 0 ? true : false;
        if (!is_ && !is__ && !is___) { //20191109
            if (txt.length() == 8) {
                return rand(str2Date_YYYYMMDD(txt), bool);
            } else if (txt.length() == 12) {
                return str2Date_YYYYMMDDHHmm(txt);
            } else {
                return str2Date_YYYYMMDDHHmmss(txt);
            }
        } else {
            if (is_ && !is___) {  //2019-10-21  201911
                return rand(str2Date_YYYY_M_D(txt), bool);
            } else if (is_ && is___) { //2019-07-02 10:21:21
                String[] arr = txt.split(":");
                if (arr.length == 3) {
                    return str2Date_YYYY_M_D_HMS(txt);
                } else {
                    return str2Date_YYYY_M_D_HM(txt);
                }
            } else if (is__ && !is___) {
                return rand(str2Date_YYYY__M__D(txt), bool);
            } else if (is__ && is___) {
                //str2Date_YYYY__M__D_HM
                String[] arr = txt.split(":");
                if (arr.length == 3) {
                    return str2Date_YYYY__M__D_HMS(txt);
                } else {
                    return str2Date_YYYY__M__D_HM(txt);
                }
            } else if (is___) {
                String[] arr = txt.split(":");
                if (arr.length == 3) {
                    return str2Date_YYYYMD_HMS(txt);
                } else {
                    return str2Date_YYYY_HM(txt);
                }
            }
        }
        return str2Date_YYYYMMDDHHmmss(txt);
    }


    public static Date str2Date1(String txt) throws ParseException {
        boolean is_ = txt.indexOf('-') > 0 ? true : false;
        boolean is__ = txt.indexOf("/") > 0 ? true : false;
        boolean is___ = txt.indexOf(":") > 0 ? true : false;
        if (!is_ && !is__ && !is___) { //20191109
            if (txt.length() == 8) {
                return str2Date_YYYYMMDD(txt);
            } else if (txt.length() == 12) {
                return str2Date_YYYYMMDDHHmm(txt);
            } else {
                return str2Date_YYYYMMDDHHmmss(txt);
            }
        } else {
            if (is_ && !is___) {  //2019-10-21  201911
                return str2Date_YYYY_M_D(txt);
            } else if (is_ && is___) { //2019-07-02 10:21:21
                String[] arr = txt.split(":");
                if (arr.length == 3) {
                    return str2Date_YYYY_M_D_HMS(txt);
                } else {
                    return str2Date_YYYY_M_D_HM(txt);
                }
            } else if (is__ && !is___) {
                return str2Date_YYYY__M__D(txt);
            } else if (is__ && is___) {
                //str2Date_YYYY__M__D_HM
                String[] arr = txt.split(":");
                if (arr.length == 3) {
                    return str2Date_YYYY__M__D_HMS(txt);
                } else {
                    return str2Date_YYYY__M__D_HM(txt);
                }
            } else if (is___) {
                String[] arr = txt.split(":");
                if (arr.length == 3) {
                    return str2Date_YYYYMD_HMS(txt);
                } else {
                    return str2Date_YYYY_HM(txt);
                }
            }
        }
        return str2Date_YYYYMMDDHHmmss(txt);
    }

    public static Date str2Date(String txt, String pattern) throws ParseException {
        if (StringUtils.isBlank(pattern)) {
            return str2Date_YYYY_MM_DD_HHMMSS(txt);
        } else {
            if ("yyyy-MM-dd HH:mm:ss".equals(pattern)) {
                return str2Date_YYYY_MM_DD_HHMMSS(txt);
            } else if ("yyyyMMddHHmmss".equals(pattern)) {
                return str2Date_YYYYMMDDHHmmss(txt);
            } else if ("yyyyMMddHHmm".equals(pattern)) {
                return str2Date_YYYYMMDDHHmm(txt);
            } else if ("yyyy/MM/dd HH:mm:ss".equals(pattern)) {
                return str2Date_YYYY__MM__DD_HHMMSS(txt);
            } else if ("yyyy/MM/dd".equals(pattern)) {
                return str2Date_YYYY__MM__DD(txt);
            }
        }
        return null;
    }

    public static String date2Str(Date date, String pattern) {
        if (StringUtils.isBlank(pattern)) {
            return date2Str_YYYY_MM_DD_HHMMSS(date);
        } else {
            if ("yyyy-MM-dd HH:mm:ss".equals(pattern)) {
                return date2Str_YYYY__MM__DD_HHMMSS(date);
            } else if ("yyyyMMddHHmmss".equals(pattern)) {
                return date2Str_YYYYMMDDHHmmss(date);
            } else if ("yyyy/MM/dd HH:mm:ss".equals(pattern)) {
                return date2Str_YYYY__MM__DD_HHMMSS(date);
            } else if ("yyyy/MM/dd".equals(pattern)) {
                return date2Str_YYYY__MM__DD(date);
            }
        }
        return null;
    }

    public static Date thisYear() throws ParseException {
        LocalDateTime localDateTime = LocalDateTime.now();
        String t = localDateTime.getYear() + "-01-01";
        return str2Date_YYYY_MM_DD(t);
    }


    /**
     * t1 大于等于t 返回 true
     *
     * @param t
     * @param t1
     * @return
     */
    public static boolean gt(Date t, Date t1) {
        if (DateUtils.daysBetween(t, t1) >= 0) {
            return true;
        }
        return false;
    }


    public static void main(String[] args) throws ParseException {
//        String str = "2019-10-12";
//        Date curDate = new Date();
//        String str1 = "2020-06-19";
//        String str = "20201116";
//        Date ss = str2Date(str);
//        str = date2Str_YYYYMMDDHHmmss(ss);
//        System.out.println(str);
//        if (str.endsWith("000000")) {
//            System.out.println("AAAA");
//        }
//        System.out.println(gt(ss, curDate));

//        String str = "202006241532";
//        print(str, true);

//        Date curDate = new Date();
//        System.out.println(getDay(curdate));
//        System.out.println(getMonth(curdate));
//        System.out.println(getDay(curdate, 10));

//        System.out.println(DateUtils.getDay(curDate) + DateUtils.getDay(curDate, -1, 20));

//        int curMonthDay = DateUtils.getDay(curDate);
//        int interval = curMonthDay;
//        if (curMonthDay < 15) {
//            interval += DateUtils.getDay(curDate, -1) - 19;
//        }
//
//        System.out.println(interval);

        String str = "2021-12-31 23:23:23";

//        Date now = str2Date_YYYY_MM_DD_HHMMSS(str);

        Date now = new Date();
        System.out.println(date2Str_YYYY_MM_DD_HHMMSS(localDateTimeToDate(dateToLocalDateTime(now))));
        System.out.println(date2Str_YYYY_MM_DD_HHMMSS(getMonthStart(now)));
        System.out.println(date2Str_YYYY_MM_DD_HHMMSS(getMonthNextStart(now)));
        System.out.println(date2Str_YYYY_MM_DD_HHMMSS(getMonthEnd(now)));
        System.out.println(date2Str_YYYY_MM_DD_HHMMSS(getDayStart(now)));
        System.out.println(date2Str_YYYY_MM_DD_HHMMSS(getDayEnd(now)));

        System.out.println(date2Str_YYYY_MM_DD_HHMMSS(addDay(now, 1)));
        System.out.println(date2Str_YYYY_MM_DD_HHMMSS(addDay(now, 10)));
        System.out.println(date2Str_YYYY_MM_DD_HHMMSS(addDay(now, -5)));
        System.out.println(date2Str_YYYY_MM_DD_HHMMSS(thisYear()));

        System.out.println(getDay(now));

        System.out.println(date2Str_YYYY_MM_DD_HHMMSS(beforeDays(now, 5)));

        System.out.println(DateUtils.date2Str_YYYYMMDD(DateUtils.addDay(now, -1)));

    }

    static void print(String str, boolean bool) throws ParseException {
        Date date = str2Date1(str);
        String t = date2Str_YYYY_MM_DD_HHMMSS(date);
        System.out.println(str + "     " + bool + "       " + t);
    }


}
